unit PHPFrame;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, StdCtrls, Dialogs, Spin;

type

  { TPHPModule }

  TPHPModule = class(TFrame)
    allow_url_fopen: TCheckBox;
    display_errors: TCheckBox;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    btnPHPConf: TButton;
    btnRecoveryDist: TButton;
    btnRecoveryDist1: TButton;
    cbPHPVersion: TComboBox;
    file_uploads: TCheckBox;
    GroupBox1: TGroupBox;
    GroupBox2: TGroupBox;
    GroupBox3: TGroupBox;
    Label1: TLabel;
    sememory_limit: TSpinEdit;
    seupload_max_filesize: TSpinEdit;
    sepost_max_size: TSpinEdit;
    procedure allow_url_fopenChange(Sender: TObject);
    procedure btnPHPConfClick(Sender: TObject);
    procedure btnRecoveryDistClick(Sender: TObject);
    procedure cbPHPVersionChange(Sender: TObject);
    procedure display_errorsChange(Sender: TObject);
    procedure file_uploadsChange(Sender: TObject);
    procedure sememory_limitEditingDone(Sender: TObject);
    procedure sepost_max_sizeEditingDone(Sender: TObject);
    procedure seupload_max_filesizeEditingDone(Sender: TObject);
  private
    { private declarations }
    function StringListFindName(TSL: TStringList; PName: String; var PValue: String):Integer;
  public
    { public declarations }
    constructor Create(AOwner: TComponent); override;
    function LoadPHPConf(PName: String; DefaultValue: String):String;
    procedure SetPHPConf(PName: String; Value: String);
    function LoadPHPConfInt(PName: String; DefaultValue: Integer):Integer;
    function LoadPHPConfBool(PName: String; DefaultValue: Boolean):Boolean;
    procedure SetPHPConfInt(PName: String; Value: Integer);
    procedure SetPHPConfBool(PName: String; Value: Boolean);
  end;

implementation
uses MainForm, functions;

{$R *.lfm}

{ TPHPModule }

procedure TPHPModule.cbPHPVersionChange(Sender: TObject);
begin
  if not LoadingDataStatus then
  begin
    LoadingDataStatus := True;
    Log('PHP版本从'+PHPStatus.version+'切换为：'+cbPHPVersion.Text);
    Main.Apache.ServiceStop;
    Main.Apache.ServiceUninstall;
    PHPStatus.version := cbPHPVersion.Text;
    ChangeProgramVersion(0);
    Main.Apache.ServiceStart;
    LoadingDataStatus := False;
  end;
end;

procedure TPHPModule.display_errorsChange(Sender: TObject);
begin
  if not LoadingDataStatus then
  begin
    SetPHPConfBool('display_errors', display_errors.Checked);
    if Main.Apache.ServiceStatus then
      Main.Apache.ServiceRestart;
  end;
end;

procedure TPHPModule.file_uploadsChange(Sender: TObject);
begin
  if not LoadingDataStatus then
  begin
    SetPHPConfBool('file_uploads', file_uploads.Checked);
    if Main.Apache.ServiceStatus then
      Main.Apache.ServiceRestart;
  end;
end;

procedure TPHPModule.sememory_limitEditingDone(Sender: TObject);
begin
  if not LoadingDataStatus then
  begin
    SetPHPConf('memory_limit', sememory_limit.Text+'M');
    if Main.Apache.ServiceStatus then
      Main.Apache.ServiceRestart;
  end;
end;

procedure TPHPModule.sepost_max_sizeEditingDone(Sender: TObject);
begin
  if not LoadingDataStatus then
  begin
    SetPHPConf('post_max_size', sepost_max_size.Text+'M');
    if Main.Apache.ServiceStatus then
      Main.Apache.ServiceRestart;
  end;
end;

procedure TPHPModule.seupload_max_filesizeEditingDone(Sender: TObject);
begin
  if not LoadingDataStatus then
  begin
    SetPHPConf('upload_max_filesize', seupload_max_filesize.Text+'M');
    if Main.Apache.ServiceStatus then
      Main.Apache.ServiceRestart;
  end;
end;

function TPHPModule.StringListFindName(TSL: TStringList; PName: String;
  var PValue: String): Integer;
var
  i, posindex : Integer;
  TempStr, TKey, TValue : String;
begin
  // 遍历查找
  for i := 0 to TSL.Count - 1 do
  begin
    TempStr := Trim(TSL[i]);
    // 去除注释
    posindex := pos(';', TempStr);
    if posindex > 0 then
    begin
      if posindex = 1 then continue;
      TempStr := TrimRight(Copy(TempStr, 1, posindex - 1));
    end;
    // 查找等号
    posindex := pos('=', TempStr);
    if posindex <= 1 then continue; // 等号不存在或者等号在第一位
    TKey := TrimRight(Copy(TempStr, 1, posindex - 1));

    if Length(TempStr) = posindex then TValue := '' // 等号在最后
    else TValue := TrimLeft(Copy(TempStr, posindex + 1, Length(TempStr) - posindex));

    if Tkey = PName then
    begin
      PValue := TValue;
      Result := i;
      exit;
    end;
  end;
  Result := -1;
end;

constructor TPHPModule.Create(AOwner: TComponent);
var
  DirPath: String;
  TSL: TStringList;
  i: Integer;
begin
  inherited Create(AOwner);


    // 检测不存在的版本，并删除
  TSL := TStringList.Create;
  DirPath := ExpandFileName(ExtractFilePath(ParamStr(0))+'..\program\php') + '\';
  for i := 0 to cbPHPVersion.Items.Count - 1 do
  begin
    if DirectoryExists(DirPath + cbPHPVersion.Items[i]) then
      TSL.Add(cbPHPVersion.Items[i]);
  end;
  cbPHPVersion.Items.Text:=TSL.Text;
  TSL.Free;

  cbPHPVersion.ItemIndex := cbPHPVersion.Items.IndexOf(PHPStatus.version);

  // 当前版本不存在
  if cbPHPVersion.ItemIndex = -1 then
  begin
    if cbPHPVersion.Items.Count > 0 then
    begin
      cbPHPVersion.ItemIndex := 0;
      PHPStatus.version := cbPHPVersion.Items[0];
      ChangeProgramVersion(3);
    end;
  end;

  // 读取配置
  file_uploads.Checked := LoadPHPConfBool('file_uploads', True);
  allow_url_fopen.Checked := LoadPHPConfBool('allow_url_fopen', True);
  display_errors.Checked := LoadPHPConfBool('display_errors', False);
  seupload_max_filesize.Value := LoadPHPConfInt('upload_max_filesize', 2);
  sememory_limit.Value := LoadPHPConfInt('memory_limit', 128);
  sepost_max_size.Value := LoadPHPConfInt('post_max_size', 8);
end;

function TPHPModule.LoadPHPConf(PName: String; DefaultValue: String): String;
var
  PHPIni: String;
  TSL: TStringList;
begin
  PHPIni := ExpandFileName(ExtractFilePath(ParamStr(0))+'..\program\php\'+PHPStatus.version+'\php.ini');
  TSL := TStringList.Create;
  TSL.LoadFromFile(PHPIni);

  if StringListFindName(TSL, PName, Result) = -1 then // 没有找到
    result := DefaultValue;
  TSL.Free;
end;

procedure TPHPModule.SetPHPConf(PName: String; Value: String);
var
  PHPIni: String;
  TSL: TStringList;
  Index: Integer;
  PValue: String;
begin
  PHPIni := ExpandFileName(ExtractFilePath(ParamStr(0))+'..\program\php\'+PHPStatus.version+'\php.ini');
  TSL := TStringList.Create;
  TSL.LoadFromFile(PHPIni);

  Index := StringListFindName(TSL, PName, PValue);
  if Index >= 0 then
  begin
    TSL[Index] := PName + ' = ' + Value;
  end else
  begin
    TSL.Add(PName + ' = ' + Value);
  end;
  TSL.SaveToFile(PHPIni);
  TSL.Free;
end;

function TPHPModule.LoadPHPConfInt(PName: String; DefaultValue: Integer
  ): Integer;
var
  ResultStr: String;
  c: Char;
begin
  ResultStr := LoadPHPConf(PName, '');
  if ResultStr = '' then
    Result := DefaultValue
  else begin
    try
      c := ResultStr[Length(ResultStr)];
      if (c >= '0') and (c <= '9') then
        Result := StrToInt(ResultStr)
      else
      begin
        Result := StrToInt(Copy(ResultStr, 1, Length(ResultStr) - 1));
        c := LowerCase(c);
        if c = 'g' then Result := Result * 1024;
        if c = 'k' then Result := Result div 1024;
      end;

    except
      Result := DefaultValue;
    end;
  end;
end;

function TPHPModule.LoadPHPConfBool(PName: String; DefaultValue: Boolean
  ): Boolean;

var
  ResultStr: String;
begin
  ResultStr := LowerCase(LoadPHPConf(PName, ''));
  if (ResultStr = 'on') or (ResultStr = 'off') then
  begin
    if ResultStr = 'on' then
      Result := True
    else
      Result := False
  end else Result := DefaultValue;
end;

procedure TPHPModule.SetPHPConfInt(PName: String; Value: Integer);
begin
  SetPHPConf(PName, IntToStr(Value));
end;

procedure TPHPModule.SetPHPConfBool(PName: String; Value: Boolean);
var
  ValueStr: String;
begin
  if Value then ValueStr := 'On'
  else ValueStr := 'Off';
  SetPHPConf(PName, ValueStr);
end;

procedure TPHPModule.btnPHPConfClick(Sender: TObject);
var
  CMD: String;
begin
  case (Sender as TButton).Tag of
    0: CMD := 'notepad.exe ..\program\php\'+PHPStatus.version+'\php.ini';
  end;
  RunCMD(CMD);
end;

procedure TPHPModule.allow_url_fopenChange(Sender: TObject);
begin
  if not LoadingDataStatus then
  begin
    SetPHPConfBool('allow_url_fopen', allow_url_fopen.Checked);
    if Main.Apache.ServiceStatus then
      Main.Apache.ServiceRestart;
  end;
end;

procedure TPHPModule.btnRecoveryDistClick(Sender: TObject);
var
  FileName, FilePath: String;
begin
  if MessageDlg('提示','您确实要恢复php.ini文件么？如果您修改过php.ini，那么所有修改将全部删除。',mtInformation,[mbYes, mbNo], 0) = mrYes then
  begin
    if Main.Apache.ServiceStatus then
      Main.Apache.ServiceStop;
    FilePath := ExpandFileName(ExtractFilePath(ParamStr(0))+'..\program\php\'+PHPStatus.version);
    if PHPStatus.version = '5.2' then
    begin
      if (Sender as TButton).Tag = 0 then
        FileName := 'php.ini-dist'
      else FileName := 'php.ini-recommended';
    end else
    begin
      if (Sender as TButton).Tag = 0 then
        FileName := 'php.ini-production'
      else FileName := 'php.ini-development';
    end;
    CopyFile(FilePath + '\' + FileName, FilePath + '\php.ini', [cffOverwriteFile]);
    Log('恢复php.ini为'+FileName);
    Main.Apache.ServiceStart;
  end;
end;

end.

